/*
 * @(#)BiomeMap.java     14/08/02
 * 
 * Author             Rick Wilson
 * Copyright (c) 2014 Rick Wilson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of 'Taareekah' nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */



package world;

//~--- non-JDK imports --------------------------------------------------------

import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;

import parameters.ParameterGroup;

//~--- JDK imports ------------------------------------------------------------

import java.io.Serializable;

import java.nio.ByteBuffer;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.management.JMException;

/**
 * A map of what biome is present at each position on the world map.
 * @author rick
 */
public class BiomeMap implements Serializable {

    /** Field description */
    private UUID[]	map;

    /** Field description */
    private int	size;

    /** Field description */
    private transient Material	material;

    /** Field description */
    private Map<UUID, BiomeType>	biomes;

    /**
     *
     * @param size
     * @throws Exception
     */
    public BiomeMap(int size) throws Exception {
	biomes	= new HashMap<>();
	resize(size);
    }

    /**
     *
     * @param id
     * @return
     * @throws Exception
     */
    public BiomeType getBiomeTypeByUUID(UUID id) throws Exception {
	return biomes.get(id);
    }

    /**
     *
     * @param name
     * @return
     */
    public boolean hasBiomeTypeByName(String name) {
	for (Map.Entry<UUID, BiomeType> e : biomes.entrySet()) {
	    if (e.getValue().getName().compareTo(name) == 0) {
		return true;
	    }
	}

	return false;
    }

    /**
     *
     * @param p
     * @return
     * @throws Exception
     */
    public boolean addBiomeType(ParameterGroup p) throws Exception {
	BiomeType	type	= new BiomeType(p);

	if (hasBiomeTypeByName(type.getName())) {
	    return false;
	}

	biomes.put(type.getUUID(), type);

	return true;
    }

    /**
     * Method description
     *
     *
     * @param x
     * @param y
     *
     * @return
     *
     * @throws Exception
     */
    private int[] getColorAtPoint(int x, int y) throws Exception {
	BiomeType	type	= getBiomeTypeByUUID(map[x + y * size]);

	return type.getColor();
    }

    /**
     *
     * @return
     */
    public Material getMaterial() {
	return material;
    }

    /**
     *
     * @param mat
     */
    public void setMaterial(Material mat) {
	material	= mat;
    }

    /**
     *
     * @param asset_manager
     * @return
     * @throws Exception
     */
    public Material createMaterial(AssetManager asset_manager) throws Exception {
	if (material != null) {
	    return material;
	}

	material	= new Material(asset_manager, "Common/MatDefs/Misc/Unshaded.j3md");
	material.setTexture("ColorMap", createTexture());

	return material;
    }

    /**
     *
     * @return
     * @throws Exception
     */
    public Texture createTexture() throws Exception {
	ByteBuffer	rgb_bytes	= ByteBuffer.allocateDirect(size * size * 3);

	for (int i = 0; i < size; i++) {
	    for (int j = 0; j < size; j++) {

		// int base = (i + (size - 1 - j) * size) * 3;
		int	base	= (i + j * size) * 3;
		int[]	rgb	= getColorAtPoint(i, j);

		rgb_bytes.put(base, (byte) rgb[0]);
		rgb_bytes.put(base + 1, (byte) rgb[1]);
		rgb_bytes.put(base + 2, (byte) rgb[2]);
	    }
	}

	Image	new_rgb	= new Image(Image.Format.RGB8, size, size, rgb_bytes);
	Texture	texture	= new Texture2D(new_rgb);

	return texture;
    }

    /**
     *
     * @return
     */
    public Map<String, BiomeType> getBiomeTypes() {
	HashMap<String, BiomeType>	ret	= new HashMap<>();

	for (Map.Entry<UUID, BiomeType> entry : biomes.entrySet()) {
	    ret.put(entry.getValue().getName(), entry.getValue());
	}

	return ret;
    }

    /**
     *
     * @param size
     * @throws Exception
     */
    public void resize(int size) throws Exception {
	if (size <= 0) {
	    throw new JMException("Invalid size");
	}

	map		= null;
	map		= new UUID[size * size];
	this.size	= size;
    }

    /**
     *
     * @param x
     * @param y
     * @param biome
     * @throws Exception
     */
    public void setBiomeAtPoint(int x, int y, BiomeType biome) throws Exception {
	if ((x < 0) || (x >= size) || (y < 0) || (y >= size)) {
	    throw new JMException("Invalid position");
	}

	map[x + y * size]	= biome.getUUID();
    }

    /**
     *
     * @param x
     * @param y
     * @return
     * @throws Exception
     */
    public BiomeType getBiomeAtPoint(int x, int y) throws Exception {
	if ((x < 0) || (x >= size) || (y < 0) || (y >= size)) {
	    throw new JMException("Invalid position");
	}

	return getBiomeTypeByUUID(map[x + y * size]);
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
